package xgb
import(
	"fmt"
	"errors"
	"io"
)
/*
.pipsts:
*/
const(
	ERR_QUE_MOD=512
	RPL_QUE_MOD=256
	EVT_QUE_LEN=1024
)









/*
.funcs:
*/


/*
.type PipT:
*/




/*
..method evtDispatch:
*/
func(pip *PipT)evtDispatch(evtChan <-chan []byte){
	for{
		evt:=<-evtChan; if evt==nil{pip.EvtQue<-nil;break}
		evtCont:=new(EvtQueT)
		evtCont.FromClt=evt[0]&0x80!=0
		flt:=EvtCodT(evt[0]&0x7f)
		evtCont.Cod=flt


		if flt==EVT_COD_KEY_PRS||flt==EVT_COD_KEY_RLS{
			// 事件的code从2开始(0和1分别被错误和返回占用)
			evtCont.EvtP=&EvtKeyPrsT{
				KeyCode: KeyCodT(evt[1]),
				Time: BytesToUint32(evt[4:8]),
				Root: BytesToUint32(evt[8:12]),
				EvtWnd: BytesToUint32(evt[12:16]),
				ChildWnd: BytesToUint32(evt[16:20]),
				RootX: BytesToInt16(evt[20:22]),
				RootY: BytesToInt16(evt[22:24]),
				EvtX: BytesToInt16(evt[24:26]),
				EvtY: BytesToInt16(evt[26:28]),
				State: BytesToUint16(evt[28:30]),
				SameScreen: evt[30]!=0,
			}//EvtPrsT/EvtRlsT
		}//if EVT_COD_KEY_PRS/RLS


		if flt==EVT_COD_BTN_PRS||flt==EVT_COD_BTN_RLS{
			evtCont.EvtP=&EvtButPrsT{
				Button: ButCodT(evt[1]),
				Time: BytesToUint32(evt[4:8]),
				Root: BytesToUint32(evt[8:12]),
				EvtWnd: BytesToUint32(evt[12:16]),
				ChildWnd: BytesToUint32(evt[16:20]),
				RootX: BytesToInt16(evt[20:22]),
				RootY: BytesToInt16(evt[22:24]),
				EvtX: BytesToInt16(evt[24:26]),
				EvtY: BytesToInt16(evt[26:28]),
				KeyButMsk: KeyButMskT(BytesToUint16(evt[28:30])),
				SameScreen: evt[30]!=0,
			}//EvtButPrsT/EvtButRlsT
		}//if EVT_COD_BTN_PRS/RLS


		if flt==EVT_COD_MOTION{
			evtCont.EvtP=&EvtMotionT{
				Hint: evt[1]!=0,
				Time: BytesToUint32(evt[4:8]),
				Root: BytesToUint32(evt[8:12]),
				EvtWnd: BytesToUint32(evt[12:16]),
				ChildWnd: BytesToUint32(evt[16:20]),
				RootX: BytesToInt16(evt[20:22]),
				RootY: BytesToInt16(evt[22:24]),
				EvtX: BytesToInt16(evt[24:26]),
				EvtY: BytesToInt16(evt[26:28]),
				KeyButMsk: KeyButMskT(BytesToUint16(evt[28:30])),
				SameScreen: evt[30]!=0,
			}//EvtMotionT
		}//if EVT_COD_MOTION


		if flt==EVT_COD_ENT||flt==EVT_COD_LV{
			evtCont.EvtP=&EvtEntT{
				Detail: EntLvDetT(evt[1]),
				Time: BytesToUint32(evt[4:8]),
				Root: BytesToUint32(evt[8:12]),
				EvtWnd: BytesToUint32(evt[12:16]),
				Child: BytesToUint32(evt[16:20]),
				RootX: int16(BytesToUint16(evt[20:22])),
				RootY: int16(BytesToUint16(evt[22:24])),
				EvtX: int16(BytesToUint16(evt[24:26])),
				EvtY: int16(BytesToUint16(evt[26:28])),
				KeyButMsk: KeyButMskT(BytesToUint16(evt[28:30])),
				Mode: EntLvModT(evt[30]),
				Focus: evt[31]&1==1,
				SameScreen: evt[31]&2==2,
			}//EvtEntT
		}//if EVT_COD_ENT/LV


		if flt==EVT_COD_FOC_IN||flt==EVT_COD_FOC_OUT{
			evtCont.EvtP=&EvtFocusInT{
				EvtWnd: BytesToUint32(evt[4:8]),
				Stat: FocusStatT(evt[1]),
				Mod: FocusModT(evt[8]),
			}//EvtFocusInT
		}//if EVT_COD_FOC_IN/OUT


		if flt==EVT_COD_KEY_MAP{
			keyCods:=[]KeyCodT{}
			var i, j KeyCodT
			for i=1;i<32;i++{
				for j=0;j<8;j++{
					if (evt[i]>>j)&1==1{keyCods=append(keyCods, (i-1)*8+j+8)}
				}
			}
			evtCont.EvtP=keyCods
		}//if EvtKeyMapT


		if flt==EVT_COD_EXPOSE{
			evtCont.EvtP=&EvtExposeT{
				Wnd: BytesToUint32(evt[4:8]),
				X: BytesToUint16(evt[8:10]),
				Y: BytesToUint16(evt[10:12]),
				Width: BytesToUint16(evt[12:14]),
				Height: BytesToUint16(evt[14:16]),
				Count: BytesToUint16(evt[16:18]),
			}//EvtExposeT
		}//if EVT_COD_EXPOSE


		if flt==EVT_COD_GRAPH_EXPOSE{
			evtCont.EvtP=&EvtGraphExposeT{
				Drawable: BytesToUint32(evt[4:8]),
				X: BytesToUint16(evt[8:10]),
				Y: BytesToUint16(evt[10:12]),
				Width: BytesToUint16(evt[12:14]),
				Height: BytesToUint16(evt[14:16]),
				Count: BytesToUint16(evt[18:20]),
				MajorOpcode: uint16(evt[20]),
				MinorOpcode: BytesToUint16(evt[16:18]),
			}//EvtGraphExposeT
		}//if EVT_COD_GRAPH_EXPOSE


		if flt==EVT_COD_NO_EXPOSE{
			evtCont.EvtP=&EvtNoExposeT{
				Drawable: BytesToUint32(evt[4:8]),
				MajorOpcode: uint16(evt[10]),
				MinorOpcode: BytesToUint16(evt[8:10]),
			}//EvtNoExposeT
		}//if EVT_COD_NO_EXPOSE


		if flt==EVT_COD_OBSCURE_CHG{
			evtCont.EvtP=&EvtObscureChgT{
				Wnd: BytesToUint32(evt[4:8]),
				Stat: ObscureChgStatT(evt[8]),
			}//EvtObscureChgT
		}//if EVT_COD_OBSCURE_CHG


		if flt==EVT_COD_CREAT{
			evtCont.EvtP=&EvtCreatT{
				Parent: BytesToUint32(evt[4:8]),
				EvtWnd: BytesToUint32(evt[8:12]),
				X: BytesToInt16(evt[12:14]),
				Y: BytesToInt16(evt[14:16]),
				Width: BytesToUint16(evt[16:18]),
				Height: BytesToUint16(evt[18:20]),
				Border: BytesToUint16(evt[20:22]),
				Direct: evt[22]!=0,
			}//EvtCreatT
		}//if EVT_COD_CREAT


		if flt==EVT_COD_DSTRY{
			evtCont.EvtP=&EvtDstryT{
				EvtWnd: BytesToUint32(evt[4:8]),
				DstryWnd: BytesToUint32(evt[8:12]),
			}//EvtDstryT
		}//if EVT_COD_DSTRY


		if flt==EVT_COD_UNMAP{
			evtCont.EvtP=&EvtUnmapT{
				EvtWnd: BytesToUint32(evt[4:8]),
				Wnd: BytesToUint32(evt[8:12]),
				FromConfig: evt[12]!=0,
			}//EvtUnmapT
		}//if EVT_COD_UNMAP


		if flt==EVT_COD_MAP{
			evtCont.EvtP=&EvtMapT{
				EvtWnd: BytesToUint32(evt[4:8]),
				Wnd: BytesToUint32(evt[8:12]),
				Direct: evt[12]!=0,
			}//EvtMapT
		}//if EVT_COD_MAP


		if flt==EVT_COD_MAP_RQST{
			evtCont.EvtP=&EvtMapRqstT{
				Parent: BytesToUint32(evt[4:8]),
				Wnd: BytesToUint32(evt[8:12]),
			}//EvtMapRqstT
		}//if EVT_COD_MAP_RQST


		if flt==EVT_COD_REPARENT{
			evtCont.EvtP=&EvtReparentT{
				EvtWnd: BytesToUint32(evt[4:8]),
				Wnd: BytesToUint32(evt[8:12]),
				NewParent: BytesToUint32(evt[12:16]),
				X: BytesToInt16(evt[16:18]),
				Y: BytesToInt16(evt[18:20]),
				Direct: evt[20]!=0,
			}//EvtReparentT
		}//if EVT_COD_REPARENT


		if flt==EVT_COD_CONF{
			evtCont.EvtP=&EvtConfT{
				EvtWnd: BytesToUint32(evt[4:8]),
				Wnd: BytesToUint32(evt[8:12]),
				ZWnd: BytesToUint32(evt[12:16]),
				X: BytesToInt16(evt[16:18]),
				Y: BytesToInt16(evt[18:20]),
				Width: BytesToUint16(evt[20:22]),
				Height: BytesToUint16(evt[22:24]),
				Border: BytesToUint16(evt[24:26]),
				Direct: evt[26]!=0,
			}//EvtConfT
		}//if EVT_COD_CONF


		if flt==EVT_COD_CONF_RQST{}//if EVT_COD_CONF_RQST


		if flt==EVT_COD_GRAV{
			evtCont.EvtP=&EvtGravT{
				EvtWnd: BytesToUint32(evt[4:8]),
				Wnd: BytesToUint32(evt[8:12]),
				X: BytesToInt16(evt[12:14]),
				Y: BytesToInt16(evt[14:16]),
			}//EvtGravT
		}//if EVT_COD_GRAV


		if flt==EVT_COD_RESIZE_RQST{
			evtCont.EvtP=&EvtResizeRqstT{
				Wnd: BytesToUint32(evt[4:8]),
				Width: BytesToUint16(evt[8:10]),
				Height: BytesToUint16(evt[10:12]),
			}//EvtResizeRqstT
		}//if EVT_COD_RESIZE_RQST


		if flt==EVT_COD_CIRCULATE{}//if EVT_COD_CIRCULATE


		if flt==EVT_COD_CIRCULATE_RQST{}//if EVT_COD_CIRCULATE_RQST






		pip.EvtQue<-evtCont
	}//for
}//evtDispatch




/*
..method rplDispatch:
*/
func(pip *PipT)rplDispatch(rplChan <-chan *RplQueT){
	for{
		rpl:=<-rplChan; if rpl==nil{break}
		switch rpl.req{
		case 3:
			(*rpl.rplP.(**GetWndAttrRplT))=&GetWndAttrRplT{
				MapState: MapStateT(rpl.data[26]),
				Visual: BytesToUint32(rpl.data[8:12]),
				Class: WndClsT(BytesToUint16(rpl.data[12:14])),
				Colormap: BytesToUint32(rpl.data[28:32]),
				NoPropagateEventMask: EvtMskT(BytesToUint16(rpl.data[40:42])),
				AllEventMask: EvtMskT(BytesToUint32(rpl.data[32:36])),
				MyEventMask: EvtMskT(BytesToUint32(rpl.data[36:40])),
				BackStore: BackStoreT(rpl.data[1]),
				SaveUnder: rpl.data[24]!=0,
				BackPlane: PixMskT(BytesToUint32(rpl.data[16:20])),
				BackPixel: PixMskT(BytesToUint32(rpl.data[20:24])),
				BitGravity: BitGravT(rpl.data[14]),
				WinGravity: WndGravT(rpl.data[15]),
				OverrideRedirect: rpl.data[27]!=0,
				MapIsInstalled: rpl.data[25]!=0,
			}//GetWndAttrRplT
		default:
			fmt.Println("rplDispatch default")
		}//switch
	}//for
}//rplDispatch







/*
..method dispatch:
*/
func(pip *PipT)dispatch(){
	rplChan:=make(chan *RplQueT, RPL_QUE_MOD/8)
	evtChan:=make(chan []byte, EVT_QUE_LEN/8)
	go pip.rplDispatch(rplChan)
	go pip.evtDispatch(evtChan)
	baseData:=make([]byte, 32)
	for {
		_,err:=pip.con.Read(baseData); if err!=nil{rplChan<-nil;evtChan<-nil
			if errors.Is(err, io.EOF){break}else{panic(err)}
		}
		
		sqc:=BytesToUint16(baseData[2:4])
		pip.rtSqc=sqc
		switch baseData[0]{
		case 0:
			v:=pip.errQue[sqc%ERR_QUE_MOD]
			*v=&ErrT{
				Typ: baseData[1],
				Val: BytesToUint32(baseData[4:8]),
			}
		case 1:
			ex:=make([]byte, 12)
			_,err:=pip.con.Read(ex); if err!=nil{rplChan<-nil;panic(err)}
			ex=append(baseData, ex...)
			pip.rplQue[sqc%RPL_QUE_MOD].data=ex
			rplChan<-pip.rplQue[sqc%RPL_QUE_MOD]
		default:
			evtChan<-baseData
		}//switch
	}//for
}//dispatch